package com.progenies.ecg.asm31.util;

import java.util.HashMap;

import org.objectweb.asm.Type;

/**
 * Allow registration of variables, obtaining its type (local/field) and index
 * @author ofc587a87
 *
 */
public class VariableRegister
{
	protected VariableRegister parentRegister;
	
	protected HashMap<String, Variable> variablesMap=new HashMap<String, VariableRegister.Variable>();
	
	protected int localVariablesCount;
	
	protected int maxCount=0;

	public VariableRegister() {}

	
	public VariableRegister(VariableRegister parent)
	{
		this.parentRegister=parent;
	}
	
	public Variable getVariable(String name)
	{
		if(this.variablesMap.containsKey(name))
			return this.variablesMap.get(name);
		else if(this.parentRegister!=null)
			return this.parentRegister.getVariable(name);
		else
			return null;
	}

	public int registerLocalVariable(String name, Type type)
	{
		Variable var=new Variable();
		var.name=name;
		var.index=getCurrentVariablesCount();
		var.local=true;
		var.type=type;
		var.staticVar=false;

		localVariablesCount+=type.getSize();
		
		setMaxCount(getCurrentVariablesCount());
		
		this.variablesMap.put(name, var);
		
		return var.getIndex();
	}

	public int registerField(String name, Type type, int modifiers[])
	{
		Variable var=new Variable();
		var.name=name;
		var.index=-1;
		var.local=false;
		var.type=type;
		var.staticVar=GenerationUtils.isStatic(modifiers);
		
		setMaxCount(getCurrentVariablesCount());
		
		this.variablesMap.put(name, var);
		
		return var.getIndex();
	}
	
	private void setMaxCount(int maxValue)
	{
		if(maxValue>this.maxCount)
		{
			this.maxCount=maxValue;

			if(parentRegister!=null)
				parentRegister.setMaxCount(maxValue);
		}
	}
	
	public int getMaxCount()
	{
		return this.maxCount;
	}
	
	
	private int getCurrentVariablesCount()
	{
		return (parentRegister==null?0:parentRegister.getCurrentVariablesCount())+localVariablesCount;
	}
	
	
	public int getLocalVariablesCount()
	{
		return localVariablesCount;
	}
	
	public String[] getLocalVariablesNames()
	{
		String result[]=new String[localVariablesCount];
		
		int index=0;
		for(Variable var : variablesMap.values())
		{
			if(var.isLocal())
				result[index++]=var.name;
		}
		return result;
	}

	




	public static final class Variable
	{
		private boolean local;
		private boolean staticVar;
		
		private int index;
		private String name;
		private Type type;
		
		
		
		public boolean isLocal() {
			return local;
		}
		
		public boolean isStatic() {
			return staticVar;
		}
		
		public int getIndex() {
			return index;
		}
		
		public String getName() {
			return name;
		}

		public Type getType() {
			return type;
		}

		public void setType(Type type) {
			this.type = type;
		}
	}
		
}
